package kr.pe.johnkim.waiting.mobile.controller;

import kr.pe.johnkim.waiting.mobile.domain.WaitingEvent;
import kr.pe.johnkim.waiting.mobile.service.WaitingEventService;
import kr.pe.johnkim.waiting.mobile.util.WaitingCommon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * Waiting 이벤트 관련 controller 클래스 이다.
 *
 * @author : John_Kim <cale9797@gmail.com>
 * @date : 13. 4. 24.
 */
@Controller
@RequestMapping(value = "/waitingEventController")
public class WaitingEventController {

    // SLF4J Logging
    private Logger logger = LoggerFactory.getLogger(WaitingEventController.class);

    @Autowired
    private WaitingEventService waitingEventService;

    @Autowired
    private HttpServletRequest httpServletRequest;

    // 이미지 업로드 Directory.
    private @Value("${waiting.upload.image.directory}") String uploadImageDirectory;

    // 이미지 업로드 URL.
    private @Value("${waiting.upload.image.url}") String uploadImageUrl;

    // 썸네일 업로드 Directory.
    private @Value("${waiting.upload.thumbnail.directory}") String uploadThumbDirectory;

    // 썸네일 업로드 URL.
    private @Value("${waiting.upload.thumbnail.url}") String uploadThumbnailUrl;

    /**
     * 이벤트를 등록 한다.
     *
     * @param waitingEvent
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/registerEvent", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public WaitingEvent registerEvent(@RequestBody WaitingEvent waitingEvent) throws Exception {
        logger.info("registerEvent");

        logger.info("merchantId   : {}", waitingEvent.getMerchantId());
        logger.info("subject      : {}", waitingEvent.getSubject());
        logger.info("content      : {}", waitingEvent.getContent());
        logger.info("imageFileUrl : {}", waitingEvent.getImageFileUrl());
        logger.info("activateYn   : {}", waitingEvent.getActivateYn());
        logger.info("modifyDate   : {}", waitingEvent.getModifyDate());
        logger.info("registerDate : {}", waitingEvent.getRegisterDate());

        WaitingEvent result = new WaitingEvent();

        try {
            this.waitingEventService.registerEvent(waitingEvent);
            result.setResult("SUCCESS");
            logger.info("success to register event.");
        } catch (Exception e) {
            result.setResult("FAIL");
            logger.error("fail to register event.");
        }

        return result;
    }

    /**
     * 첨부 이미지 파일과 함게 가맹점 이벤트를 등록 한다.
     * 위의 registerEvent 메소드와 동일하며, 이미지 파일 업로드 기능이 추가되었다.
     *
     * 이미지 첨부는 옵션이기때문에 동일 transaction 에서 처리하지 않고 controller class 에서 처리 한다.
     * 만약 이미지 업로드시에 오류가 발생하면 비활성화 하고 다시 이벤트를 등록해야 한다.
     *
     * @param merchantId
     * @param subject
     * @param content
     * @param imageFileUrl
     * @param activateYn
     * @param modifyDate
     * @param registerDate
     * @param file
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/registerEventWithImage", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public WaitingEvent registerEventWithImage(
            @RequestParam("merchantId") String merchantId,
            @RequestParam("subject") String subject,
            @RequestParam("content") String content,
            @RequestParam("imageFileUrl") String imageFileUrl,
            @RequestParam("activateYn") String activateYn,
            @RequestParam("modifyDate") String modifyDate,
            @RequestParam("registerDate") String registerDate,
            @RequestParam("file")MultipartFile file
    ) throws Exception {
        logger.info("registerEventWithImage");

        WaitingEvent waitingEvent = new WaitingEvent();

        waitingEvent.setMerchantId(merchantId);
        waitingEvent.setSubject(subject);
        waitingEvent.setContent(content);
        waitingEvent.setImageFileUrl(imageFileUrl);
        waitingEvent.setActivateYn(activateYn);
        waitingEvent.setModifyDate(modifyDate);
        waitingEvent.setRegisterDate(registerDate);

        logger.info("merchantId   : {}", waitingEvent.getMerchantId());
        logger.info("subject      : {}", waitingEvent.getSubject());
        logger.info("content      : {}", waitingEvent.getContent());
        logger.info("imageFileUrl : {}", waitingEvent.getImageFileUrl());
        logger.info("activateYn   : {}", waitingEvent.getActivateYn());
        logger.info("modifyDate   : {}", waitingEvent.getModifyDate());
        logger.info("registerDate : {}", waitingEvent.getRegisterDate());

        WaitingEvent result = new WaitingEvent();

        try {

            if(!file.isEmpty()) {
                // 이미지 경로를 다시 설정 한다.
                String uploadImagePath = this.httpServletRequest.getSession().getServletContext().getRealPath("/") + uploadImageDirectory;
                logger.info("uploadPath : {}", uploadImagePath);
                waitingEvent.setImageFileUrl(uploadImageUrl + file.getOriginalFilename());
                logger.info("imageFileUrl : {}", waitingEvent.getImageFileUrl());

                // 썸네일 경로를 다시 설정 한다.
                String uploadThumbnailPath = this.httpServletRequest.getSession().getServletContext().getRealPath("/") + uploadThumbDirectory;
                waitingEvent.setThumbnailUrl(uploadThumbnailUrl + file.getOriginalFilename());
                logger.info("uploadThumbnailPath  : {}", uploadThumbnailPath);

                // 이벤트를 등록 한다.
                this.waitingEventService.registerEventWithImage(waitingEvent, uploadImagePath, uploadThumbnailPath, file);

                result.setResult("SUCCESS");
                logger.info("success to register event.");
            } else {
                result.setResult("FAIL");
                logger.error("fail to register event.");
            }
        } catch (Exception e) {
            result.setResult("FAIL");
            logger.error("fail to register event.");
        }

        return result;
    }

    /**
     * 이벤트 정보룰 수정한다.
     *
     * @param waitingEvent
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateEventInformation", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public WaitingEvent updateEventInformation(@RequestBody WaitingEvent waitingEvent) throws Exception {
        logger.info("updateEventInformation");

        logger.info("idWaitingEvents : {}", waitingEvent.getIdWaitingEvents());
        logger.info("merchantId      : {}", waitingEvent.getMerchantId());
        logger.info("subject         : {}", waitingEvent.getSubject());
        logger.info("content         : {}", waitingEvent.getContent());
        logger.info("imageFileUrl    : {}", waitingEvent.getImageFileUrl());
        logger.info("activateYn      : {}", waitingEvent.getActivateYn());
        logger.info("modifyDate      : {}", waitingEvent.getModifyDate());

        WaitingEvent result = new WaitingEvent();

        try {
            this.waitingEventService.updateEventInformation(waitingEvent);
            result.setResult("SUCCESS");
            logger.info("success to update event information.");
        } catch (Exception e) {
            result.setResult("FAIL");
            logger.error("fail to update event information.");
        }

        return result;
    }

    /**
     * 이벤트 정보를 가져 온다.
     *
     * @param waitingEvent
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/selectEventInformation", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public WaitingEvent selectEventInformation(@RequestBody WaitingEvent waitingEvent) throws Exception {
        logger.info("selectEventInformation");

        logger.info("idWaitingEvents : {}", waitingEvent.getIdWaitingEvents());
        logger.info("merchantId      : {}", waitingEvent.getMerchantId());
        logger.info("activateYn      : {}", waitingEvent.getActivateYn());

        return this.waitingEventService.selectEventInformation(waitingEvent);
    }

    /**
     * 이벤트 목록을 가져 온다. 사용자의 smart phone 에 출력 한다.
     *
     * @param waitingEvent
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/selectUserEventList", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public List<WaitingEvent> selectUserEventList(@RequestBody WaitingEvent waitingEvent) throws Exception {
        logger.info("selectUserEventList");

        logger.info("qrCode     : {}", waitingEvent.getQrCode());
        logger.info("activateYn : {}", waitingEvent.getActivateYn());

        return this.waitingEventService.selectUserEventList(waitingEvent);
    }

    /**
     * 이벤트 목록을 가져 온다. 가맹점 iPad 에 출력 된다.
     *
     * @param waitingEvent
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/selectMerchantEventList", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public List<WaitingEvent> selectMerchantEventList(@RequestBody WaitingEvent waitingEvent) throws Exception {
        logger.info("selectMerchantEventList");

        logger.info("merchantId : {}", waitingEvent.getMerchantId());
        logger.info("activateYn : {}", waitingEvent.getIdWaitingEvents());

        return this.waitingEventService.selectMerchantEventList(waitingEvent);
    }

    /**
     * 이벤트 활성화 여부를 업데이트 한다.
     *
     * @param waitingEvent
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateEventActivateYn", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public WaitingEvent updateEventActivateYn(@RequestBody WaitingEvent waitingEvent) throws Exception {
        logger.info("updateEventActivateYn");

        logger.info("idWaitingEvents : {}", waitingEvent.getIdWaitingEvents());
        logger.info("merchantId      : {}", waitingEvent.getMerchantId());
        logger.info("activateYn      : {}", waitingEvent.getActivateYn());
        logger.info("modifyDate      : {}", waitingEvent.getModifyDate());

        WaitingEvent result = new WaitingEvent();

        try {
            this.waitingEventService.updateEventActivateYn(waitingEvent);
            result.setResult("SUCCESS");
            logger.info("success to update event activateYn.");
        } catch (Exception e) {
            result.setResult("FAIL");
            logger.error("fail to update event activateYn.");
        }
        return result;
    }
}
